{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%matplotlib inline\n",
    "import matplotlib.pyplot as plt\n",
    "import numpy as np\n",
    "import pandas as pd\n",
    "\n",
    "data=pd.read_csv(r'.\\titanic\\train.csv',index_col=0)  #读取数据，并且指定第一列作为索引\n",
    "data.head(20)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "data.drop(['Name','Ticket','Cabin'],axis=1,inplace=True)\n",
    "data['Sex']=(data['Sex']=='male').astype(int)  #把male和female变成1和0\n",
    "labels=data['Embarked'].unique().tolist()   #取出Embarked的所有唯一取值，并转换成列表  ['S','C','Q',nan]\n",
    "data['Embarked']=data['Embarked'].apply(lambda n:labels.index(n))  #用原数据中Embarked值在列表中的索引来取代原来的值  [0,1,2,3]\n",
    "data=data.fillna(0)  #处理缺失数据  可以对每一列用该列的平均值来填充该列中的空白，求平均：data['age'].mean()\n",
    "data.head(20)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "data.loc[62]   #查看 PassangerID=62的乘客的信息"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "data.describe()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "y=data['Survived'].values   #取Survided这一列的值作为数据的标签\n",
    "X=data.drop(['Survived'],axis=1).values   #原数据中删除Survived这一列，剩下的值是样本的属性值\n",
    "\n",
    "from sklearn.model_selection import train_test_split\n",
    "\n",
    "X_train,X_test,y_train,y_test=train_test_split(X,y,test_size=0.2)  #划分训练集和测试集\n",
    "print(X_train.shape,X_test.shape)  #查看训练集和测试集的形状"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from sklearn.tree import DecisionTreeClassifier\n",
    "\n",
    "model=DecisionTreeClassifier()  #创建决策树模型\n",
    "model.fit(X_train,y_train)  #训练模型\n",
    "\n",
    "train_score=model.score(X_train,y_train)  #计算模型在训练集上的得分\n",
    "test_score=model.score(X_test,y_test)  #计算模型在测试集上的得分\n",
    "\n",
    "print('train_score: ',train_score)\n",
    "print('test_score: ',test_score)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def cv_score(d):\n",
    "    model=DecisionTreeClassifier(max_depth=d)  #创建决策树模型，并指定max_depth参数的取值为d\n",
    "    model.fit(X_train,y_train)\n",
    "    train_score=model.score(X_train,y_train)\n",
    "    test_score=model.score(X_test,y_test)\n",
    "    return train_score,test_score\n",
    "\n",
    "depths=range(2,7)   #设定max_depth的取值范围\n",
    "scores=[cv_score(d) for d in depths]  #[(,),(,),(,)....(,)]  对depths设定的取值范围中的每一个值，作为参数传递给cv_score，生成模型，训练模型，评分，返回评分\n",
    "train_scores=[s[0] for s in scores]  #从返回值中挨个取出train_score\n",
    "test_scores=[s[1] for s in scores]  #从返回值中挨个取出test_score\n",
    "\n",
    "best_score_index=np.argmax(test_scores)  #找到test_scores列表中最大值的索引\n",
    "\n",
    "best_score=test_scores[best_score_index]  #最大测试得分\n",
    " \n",
    "best_param=depths[best_score_index]  #取得最大测试得分时的参数\n",
    "\n",
    "print('best param: {0}; best score: {1}'.format(best_param,best_score))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from sklearn.model_selection import GridSearchCV\n",
    "\n",
    "thresholds=np.linspace(0,0.5,50)  #指定min_impurity_split的取值范围\n",
    "\n",
    "param_grid={'min_impurity_split': thresholds}  #参数矩阵\n",
    "\n",
    "model=GridSearchCV(DecisionTreeClassifier(),param_grid,cv=5)  \n",
    "#创建决策树模型，其参数min_impurity_split从thresholds中取值，cv 表示要做几折的交叉验证\n",
    "\n",
    "model.fit(X,y)\n",
    "\n",
    "print('best param: {0}; best score: {1}'.format(model.best_params_,model.best_score_))\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "thresholds=np.linspace(0,1,50)\n",
    "thresholds2=np.linspace(0,0.5,50)\n",
    "#定义一组参数，包括参数的组合，参数的取值范围，每一个参数组合放在一个字典中，所有参数组合放在列表中\n",
    "param_grid=[\n",
    "    {'criterion':['entropy'],'min_impurity_split':thresholds},\n",
    "    {'criterion':['gini'],'min_impurity_split':thresholds2},\n",
    "    {'max_depth':range(2,7)},\n",
    "    {'min_samples_split': range(2,30,2)}\n",
    "]\n",
    "\n",
    "model=GridSearchCV(DecisionTreeClassifier(),param_grid,cv=5)\n",
    "\n",
    "model.fit(X,y)\n",
    "\n",
    "#GridSearchCV会把最佳参数和最佳得分分别保存在best_params_和best_score_中，他们是模型的属性\n",
    "\n",
    "print('best param: {0}; best score: {1}'.format(model.best_params_,model.best_score_))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#用我们上面找到的最佳参数来创建模型，并训练，测试，求得分\n",
    "\n",
    "model=DecisionTreeClassifier(criterion='entropy',min_impurity_split=0.5102040816326531) \n",
    "model.fit(X_train,y_train)\n",
    "train_score=model.score(X_train,y_train)\n",
    "test_score=model.score(X_test,y_test)\n",
    "\n",
    "print('train_score: ',train_score)\n",
    "print('test_score: ',test_score)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "#查看创建好的决策树\n",
    "\n",
    "#先用export_graphviz方法将生成的模型导出到一个.dot文件中，然后需要安装graphviz，并转换成图片格式\n",
    "\n",
    "from sklearn.tree import export_graphviz\n",
    "\n",
    "with open('titanic_2.dot','w') as f:\n",
    "    f=export_graphviz(model,out_file=f)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "安装 graphviz，一种是msi安装，一种下载压缩包后解压来用\n",
    "\n",
    "解压后，将生成的 .dot类型的文件复制到 dot.exe所在目录（graphviz的bin目录下），运行以下命令，便可得到一个png图片\n",
    "\n",
    "dot -Tpng titanic_2.dot -o titanic.png  "
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
